{
    "cells": [
        {
            "cell_type": "raw",
            "metadata": {},
            "source": [
                "---\n",
                "title: '`@register_passable`'\n",
                "description: Declares that a type should be passed in machine registers.\n",
                "css: /static/styles/page-navigation.css\n",
                "website:\n",
                "  open-graph:\n",
                "    image: /static/images/mojo-social-card.png\n",
                "  twitter-card:\n",
                "    image: /static/images/mojo-social-card.png\n",
                "---"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "You can add the `@register_passable` decorator on a struct to tell Mojo that\n",
                "the type should be passed in machine registers (such as a CPU register; subject\n",
                "to the details of the underlying architecture). For tiny data types like an\n",
                "integer or floating-point number, this is much more efficient than storing\n",
                "values in stack memory. This means the type is always passed by value and\n",
                "cannot be passed by reference.\n",
                "\n",
                "The basic `@register_passable` decorator does not change the fundamental\n",
                "behavior of a type: it still needs an `__init__()` and `__copyinit__()` method\n",
                "to be copyable (and it may have a `__del__()` method, if necessary). For example:"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 1,
            "metadata": {},
            "outputs": [],
            "source": [
                "@register_passable\n",
                "struct Pair:\n",
                "    var a: Int\n",
                "    var b: Int\n",
                "\n",
                "    fn __init__(inout self, one: Int, two: Int):\n",
                "        self.a = one\n",
                "        self.b = two\n",
                "\n",
                "    fn __copyinit__(inout self, existing: Self):\n",
                "        self.a = existing.a\n",
                "        self.b = existing.b\n",
                "\n",
                "fn test_pair():\n",
                "    var x = Pair(5, 10)\n",
                "    var y = x\n",
                "\n",
                "    print(y.a, y.b)\n",
                "    y.a = 10\n",
                "    y.b = 20\n",
                "    print(y.a, y.b)"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 2,
            "metadata": {},
            "outputs": [
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "5 10\n",
                        "10 20\n"
                    ]
                }
            ],
            "source": [
                "test_pair()"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "This behavior is what we expect from `Pair`, with or without the decorator."
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                ":::note Updated syntax\n",
                "\n",
                "Register passable types now accept standard lifecycle methods, as shown above. \n",
                "Prior to Mojo 24.1, register-passable types required a non-standard constructor that returned a value, with syntax like this: `return Self{a: one, b: two}`. \n",
                "The older syntax is still supported but will be removed in a future release. For more information about this change, see the [Mojo 24.1 release notes](/mojo/changelog#v241-2024-02-29).\n",
                "\n",
                ":::"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "You should be aware of a few other observable effects:\n",
                "\n",
                "1. `@register_passable` types cannot hold instances of types\n",
                "that are not also `@register_passable`.\n",
                "\n",
                "1. `@register_passable` types do not have a predictable identity,\n",
                "and so the `self` pointer is not stable/predictable (e.g. in hash tables).\n",
                "\n",
                "1. `@register_passable` arguments and result are exposed to C and C++ directly,\n",
                "instead of being passed by-pointer.\n",
                "\n",
                "1. `@register_passable` types cannot have a [`__moveinit__()`\n",
                "constructor](/mojo/manual/lifecycle/life.html#move-constructors), because\n",
                "values passed in a register cannot be passed by reference.\n"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "## `@register_passable(\"trivial\")`"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "Most types that use `@register_passable` are just \"bags of bits,\" which we call\n",
                "\"trivial\" types. These trivial types are simple and should be copied, moved,\n",
                "and destroyed without any custom constructors or a destructor. For these types,\n",
                "you can add the `\"trivial\"` argument, and Mojo synthesizes all the lifecycle\n",
                "methods as appropriate for a trivial register-passable type:"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 30,
            "metadata": {},
            "outputs": [],
            "source": [
                "@register_passable(\"trivial\")\n",
                "struct Pair:\n",
                "    var a: Int\n",
                "    var b: Int"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "This is similar to the [`@value`](/mojo/manual/decorators/value.html) decorator,\n",
                "except when using `@register_passable(\"trivial\")` the only lifecycle method\n",
                "you're allowed to define is the `__init__()` constructor (but you don't have\n",
                "to)—you _cannot_ define any copy or move constructors or a destructor.\n",
                "\n",
                "Examples of trivial types include:\n",
                "\n",
                "- Arithmetic types such as `Int`, `Bool`, `Float64` etc.\n",
                "- Pointers (the address value is trivial, not the data being pointed to).\n",
                "- Arrays of other trivial types, including SIMD."
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "For more information about lifecycle methods (constructors and destructors)\n",
                "see the section about [Value lifecycle](/mojo/manual/lifecycle/)."
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                ":::note TODO\n",
                "\n",
                "This decorator is due for reconsideration. Lack of custom\n",
                "copy/move/destroy logic and \"passability in a register\" are orthogonal concerns\n",
                "and should be split. This former logic should be subsumed into a more general\n",
                "[`@value(\"trivial\")`](/mojo/manual/decorators/value.html) decorator, which is\n",
                "orthogonal from `@register_passable`.\n",
                "\n",
                ":::"
            ]
        },
        {
            "attachments": {},
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "<CommentService />"
            ]
        }
    ],
    "metadata": {
        "kernelspec": {
            "display_name": "Mojo",
            "language": "mojo",
            "name": "mojo-jupyter-kernel"
        },
        "language_info": {
            "codemirror_mode": {
                "name": "mojo"
            },
            "file_extension": ".mojo",
            "mimetype": "text/x-mojo",
            "name": "mojo"
        },
        "orig_nbformat": 4
    },
    "nbformat": 4,
    "nbformat_minor": 2
}
